/*********************************************************************************************************************
 * COPYRIGHT NOTICE
 * Copyright (c) 2018,逐飞科技
 * All rights reserved.
 * 技术讨论QQ群：	一群：179029047(已满)
 *					二群：244861897(已满)
 *					三群：824575535
 *
 * 以下所有内容版权均属逐飞科技所有，未经允许不得用于商业用途，
 * 欢迎各位使用并传播本程序，修改内容时必须保留逐飞科技的版权声明。
 *
 * @file			zf_sct.c
 * @company			成都逐飞科技有限公司
 * @author			逐飞科技(QQ3184284598)
 * @version			查看doc内version文件 版本说明
 * @Software		IAR 8.3 or MDK 5.24
 * @Taobao			https://seekfree.taobao.com/
 * @date			2020-03-25
 * @note			本文件作为 LPC55S 系列芯片开源库外设文件
					提供 SCT 外设驱动
					请注意 SCT0 总共可以配置16个匹配或者捕获值
					触发匹配或者捕获时 产生对应的事件
					PWM 模式下 OUT 寄存器根据设置匹配对应事件来改变输出
					那么意味着 32bit模式下 最大设置 10 个不同周期不同占空比的 PWM
					调用SDK库则只能生成 8 个不同周期不同占空比的 PWM 库函数每个 PWM 占用两个匹配
					可以详细参考手册来学习这个部分
 ********************************************************************************************************************/

#include "zf_sct.h"

static uint32_t zf_sct0_pwm_freq;								// 统一的频率
uint32_t sct0_pwm_event[10];									// 每个通道都是由自己的事件来操作

//-------------------------------------------------------------------------------------------------------------------
//	@brief		获取 SCT 定时器的默认设置
//	@param		config			结构体
//	Sample usage:				zf_sct_get_default_config(&config);
//-------------------------------------------------------------------------------------------------------------------
void zf_sct_get_default_config (sctimer_config_t *config)
{
	SCTIMER_GetDefaultConfig (config);
//	config->enableCounterUnify = true;							// 对应 CONFIG 寄存器 [0]UNIFY 32bit 模式使能
//	config->clockMode = kSCTIMER_System_ClockMode;				// 对应 CONFIG 寄存器 [2:1]CLKMODE 选择输入 SCT 的时钟模式
//	config->clockSelect = kSCTIMER_Clock_On_Rise_Input_0;		// 对应 CONFIG 寄存器 [6:3]CKSEL 选择时钟输入通道方式 CLKMODE 不为 0x00 时启用
//	config->enableBidirection_l = false;						// 对应 CTRL 寄存器 [4]BIDIR_L 低位或32位模式 计数器上下计数模式
//	config->enableBidirection_h = false;						// 对应 CTRL 寄存器 [20]BIDIR_H 高位 计数器上下计数模式
//	config->prescale_l = 0U;									// 对应 CTRL 寄存器 [12:5]PRE_L 低位或32位模式 计数器预分频
//	config->prescale_h = 0U;									// 对应 CTRL 寄存器 [28:21]PRE_H 高位 计数器预分频
//	config->outInitState = 0U;									// 对应 OUTPUT 寄存器 [15:0]OUT 写 0 通道输出低 写 1 通道输出高
//	config->inputsync  = 0xFU;									// 对应 CONFIG 寄存器 [12:9]INSYNC 同步设置
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		修改 SCT 定时器的设置
//	@param		config			结构体
//	@param		param_index		修改的列表索引
//	@param		data			参数
//	Sample usage:				zf_sct_param_set(&config, SCT_PARAM_COUNT_MODE, COUNT_MODE_32BIT);
//	note:						这里是修改参数的示例接口 用户可以不调用这个接口直接写结构体
//-------------------------------------------------------------------------------------------------------------------
void zf_sct_param_set (sctimer_config_t *config, sct_param_list param_index, uint32_t data)
{
	assert(config != NULL);
	switch(param_index)
	{
		case SCT_PARAM_COUNT_MODE:
			config->enableCounterUnify = (sct_count_mode_list)data;
			break;
		case SCT_PARAM_CLK_MODE:
			config->clockMode = (sctimer_clock_mode_t)data;
			break;
		case SCT_PARAM_CLK_SEL:
			config->clockSelect = (sctimer_clock_select_t)data;
			break;
		case SCT_PARAM_LCOUNT_DIR:
			config->enableBidirection_l = (sct_lcount_dir_list)data;
			break;
		case SCT_PARAM_HCOUNT_DIR:
			config->enableBidirection_h = (sct_hcount_dir_list)data;
			break;
		case SCT_PARAM_PRE_L:
			config->prescale_l = data;
			break;
		case SCT_PARAM_PRE_H:
			config->prescale_h = data;
			break;
		case SCT_PARAM_OUT_INIT:
			config->outInitState = data;
			break;
		case SCT_PARAM_IN_SYNC:
			config->inputsync = data;
			break;
	}
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		初始化 SCT 定时器
//	@param		config			结构体
//	Sample usage:				zf_sct_init(&config);
//-------------------------------------------------------------------------------------------------------------------
void zf_sct_init (sctimer_config_t *config)
{
	SCTIMER_Init(SCT0, config);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		默认值初始化 SCT 定时器
//	Sample usage:				zf_sct_default_init();
//-------------------------------------------------------------------------------------------------------------------
void zf_sct_default_init (void)
{
	sctimer_config_t config_sct;
	zf_sct_get_default_config(&config_sct);
	SCTIMER_Init(SCT0, &config_sct);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		设置 SCT PWM 频率
//	@param		freq_hz			频率
//	Sample usage:				zf_sct_set_pwm_freq(10000);
//-------------------------------------------------------------------------------------------------------------------
void zf_sct_pwm_set_freq (uint32_t freq_hz)
{
	zf_sct0_pwm_freq = freq_hz;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		默认值初始化 SCT 并设置 PWM 频率
//	@param		freq_hz			频率
//	Sample usage:				zf_sct_default_pwm_init();
//-------------------------------------------------------------------------------------------------------------------
void zf_sct_default_pwm_init (uint32_t freq_hz)
{
	sctimer_config_t config_sct;
	zf_sct_get_default_config(&config_sct);
	SCTIMER_Init(SCT0, &config_sct);
	zf_sct0_pwm_freq = freq_hz;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		设置 SCT PWM 通道 有效电平 模式
//	@param		channel			通道
//	@param		level			有效电平
//	@param		mode			对齐方式
//	Sample usage:				zf_sct_setup_pwm(SCT_PWM_OUT_0, SCT_PWM_LEVEL_HIGH, SCT_PWM_MODE_EDGE);
//-------------------------------------------------------------------------------------------------------------------
status_t zf_sct_pwm_setup (sct_pwm_channel_list channel, sct_pwm_level_list level, sct_pwm_mode_list mode)
{
	sctimer_pwm_signal_param_t pwmParam;
	pwmParam.output = (sctimer_out_t)channel;
	pwmParam.dutyCyclePercent = 1;
	pwmParam.level = (sctimer_pwm_level_select_t)level;
	return SCTIMER_SetupPwm(SCT0, &pwmParam, (sctimer_pwm_mode_t)mode, zf_sct0_pwm_freq, CLOCK_GetFreq(kCLOCK_BusClk), &sct0_pwm_event[channel]);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		设置 SCT PWM 通道 有效电平 模式
//	@param		channel			通道
//	@param		duty			占空比
//	Sample usage:				zf_sct_pwm_update_duty(SCT_PWM_OUT_0, 20);
//-------------------------------------------------------------------------------------------------------------------
void zf_sct_pwm_update_duty (sct_pwm_channel_list channel, uint8_t duty)
{
	if(duty)
	{
		if(SCT0->OUT[channel].SET == 0x00)
			SCT0->OUT[channel].SET |= (0x00000001 << sct0_pwm_event[channel]);
		SCTIMER_UpdatePwmDutycycle(SCT0, (sctimer_out_t)channel, duty, sct0_pwm_event[channel]);
	}
	else
	{
		SCT0->OUT[channel].SET &= ~(0x00000001 << sct0_pwm_event[channel]);
		SCTIMER_StopTimer(SCT0, kSCTIMER_Counter_U);
		SCT0->OUTPUT &= ~(1UL << (uint32_t)channel);
		SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_U);
	}
//	SCTIMER_UpdatePwmDutycycle(SCT0, (sctimer_out_t)channel, duty, sct0_pwm_event[channel]);
}
